import 'package:flutter_riverpod/flutter_riverpod.dart';

import '../repositories/tunnel_repository.dart';
import '../../models/tunnel_models.dart';

/// 隧道状态
class TunnelState {
  const TunnelState({
    this.tunnels = const [],
    this.isLoading = false,
    this.error,
    this.connectionStates = const {},
  });

  final List<TunnelData> tunnels;
  final bool isLoading;
  final String? error;
  final Map<String, TunnelConnectionState> connectionStates;

  TunnelState copyWith({
    List<TunnelData>? tunnels,
    bool? isLoading,
    String? error,
    Map<String, TunnelConnectionState>? connectionStates,
  }) {
    return TunnelState(
      tunnels: tunnels ?? this.tunnels,
      isLoading: isLoading ?? this.isLoading,
      error: error,
      connectionStates: connectionStates ?? this.connectionStates,
    );
  }

  @override
  String toString() => 'TunnelState(tunnels: ${tunnels.length}, isLoading: $isLoading, error: $error)';
}

/// 隧道状态管理
class TunnelNotifier extends StateNotifier<TunnelState> {
  TunnelNotifier(this._tunnelRepository) : super(const TunnelState());

  final TunnelRepository _tunnelRepository;

  /// 获取隧道列表
  Future<void> fetchTunnels() async {
    if (!mounted) return;
    state = state.copyWith(isLoading: true, error: null);
    
    final result = await _tunnelRepository.getTunnels();
    if (!mounted) return;
    
    result.fold(
      (failure) {
        state = state.copyWith(isLoading: false, error: failure.message);
      },
      (tunnels) {
        state = state.copyWith(tunnels: tunnels, isLoading: false);
      },
    );
  }

  /// 创建隧道
  Future<TunnelData?> createTunnel({
    required String localHost,
    required String localPort,
    required String serverName,
    String tunnelType = 'http',
  }) async {
    if (!mounted) return null;
    state = state.copyWith(isLoading: true, error: null);
    
    final result = await _tunnelRepository.createTunnel(
      localHost: localHost,
      localPort: localPort,
      serverName: serverName,
      tunnelType: tunnelType,
    );
    if (!mounted) return null;
    
    TunnelData? createdTunnel;
    if (result.isLeft()) {
      final failure = result.fold((l) => l, (r) => null)!;
      state = state.copyWith(isLoading: false, error: failure.message);
    } else {
      final createResponse = result.fold((l) => null, (r) => r)!;
      
      // 创建隧道后需要重新获取列表以获取完整信息（包括public_url）
      await fetchTunnels();
      if (!mounted) return null;
      
      // 从列表中找到刚创建的隧道
      createdTunnel = state.tunnels.firstWhere(
        (tunnel) => tunnel.tunnelId == createResponse.tunnelId,
        orElse: () => TunnelData(
          tunnelId: createResponse.tunnelId,
          serverName: serverName,
          localHost: localHost,
          localPort: localPort,
          tunnelHost: createResponse.tunnelHost,
          tunnelPort: createResponse.tunnelPort,
          publicPort: createResponse.publicPort,
          publicAddress: 'http://${createResponse.tunnelId.split('-').first}.tunnel.example.com',
          tunnelType: tunnelType,
          isConnected: true,
        ),
      );
    }
    
    return createdTunnel;
  }

  /// 删除隧道
  Future<void> deleteTunnel(String tunnelId) async {
    if (!mounted) return;
    state = state.copyWith(isLoading: true, error: null);
    
    final result = await _tunnelRepository.deleteTunnel(tunnelId);
    if (!mounted) return;
    
    if (result.isLeft()) {
      final failure = result.fold((l) => l, (r) => null)!;
      state = state.copyWith(isLoading: false, error: failure.message);
    } else {
      final updatedTunnels = state.tunnels.where((t) => t.tunnelId != tunnelId).toList();
      final updatedConnectionStates = Map<String, TunnelConnectionState>.from(state.connectionStates)
        ..remove(tunnelId);
      state = state.copyWith(
        tunnels: updatedTunnels,
        connectionStates: updatedConnectionStates,
        isLoading: false,
      );
    }
  }

  /// 更新隧道
  Future<bool> updateTunnel({
    required String tunnelId,
    required String localHost,
    required String localPort,
    required String serverName,
    String tunnelType = 'http',
  }) async {
    if (!mounted) return false;
    state = state.copyWith(isLoading: true, error: null);
    
    final result = await _tunnelRepository.updateTunnel(
      tunnelId: tunnelId,
      localHost: localHost,
      localPort: localPort,
      serverName: serverName,
      tunnelType: tunnelType,
    );
    if (!mounted) return false;
    
    bool success = false;
    if (result.isLeft()) {
      final failure = result.fold((l) => l, (r) => null)!;
      state = state.copyWith(isLoading: false, error: failure.message);
    } else {
      final updateResponse = result.fold((l) => null, (r) => r)!;
      
      // 更新成功，立即更新对应的隧道项
      final updatedTunnels = state.tunnels.map((tunnel) {
        if (tunnel.tunnelId == tunnelId) {
          return TunnelData(
            tunnelId: tunnel.tunnelId,
            serverName: serverName,
            localHost: localHost,
            localPort: localPort,
            tunnelHost: tunnel.tunnelHost,
            tunnelPort: tunnel.tunnelPort,
            publicPort: updateResponse.publicPort,
            publicAddress: tunnel.publicAddress,
            tunnelType: tunnelType,
            isConnected: tunnel.isConnected,
            status: tunnel.status,
            createdAt: tunnel.createdAt,
            updatedAt: DateTime.now(),
          );
        }
        return tunnel;
      }).toList();
      
      state = state.copyWith(
        tunnels: updatedTunnels,
        isLoading: false,
      );
      success = true;
      
      // 可选：在后台获取最新的隧道信息（如果需要服务器端的其他更新）
      _refreshSingleTunnelInBackground(tunnelId);
    }
    
    return success;
  }

  /// 更新隧道连接状态
  void updateConnectionState(String tunnelId, TunnelConnectionState connectionState) {
    final updatedStates = Map<String, TunnelConnectionState>.from(state.connectionStates);
    updatedStates[tunnelId] = connectionState;
    state = state.copyWith(connectionStates: updatedStates);
  }

  /// 获取隧道连接状态
  TunnelConnectionState? getConnectionState(String tunnelId) {
    return state.connectionStates[tunnelId];
  }

  /// 检查隧道是否已连接
  bool isTunnelConnected(String tunnelId) {
    final connectionState = state.connectionStates[tunnelId];
    return connectionState?.status == TunnelConnectionStatus.connected;
  }

  /// 清除错误
  void clearError() {
    state = state.copyWith(error: null);
  }

  /// 刷新隧道列表
  Future<void> refresh() => fetchTunnels();

  /// 在后台刷新隧道列表，不影响加载状态
  void _refreshTunnelsInBackground() {
    _tunnelRepository.getTunnels().then((result) {
      // 检查notifier是否已经被dispose
      if (!mounted) return;
      
      result.fold(
        (failure) {
          // 后台刷新失败，不更新错误状态，避免影响用户体验
          print('后台刷新隧道列表失败: ${failure.message}');
        },
        (tunnels) {
          // 只更新隧道列表，保持当前的加载状态和错误状态
          state = state.copyWith(tunnels: tunnels);
        },
      );
    }).catchError((error) {
      print('后台刷新隧道列表异常: $error');
    });
  }

  /// 在后台刷新单个隧道信息，不影响加载状态
  void _refreshSingleTunnelInBackground(String tunnelId) {
    _tunnelRepository.getTunnels().then((result) {
      // 检查notifier是否已经被dispose
      if (!mounted) return;
      
      result.fold(
        (failure) {
          print('后台刷新单个隧道失败: ${failure.message}');
        },
        (tunnels) {
          // 找到对应的隧道并更新
          final updatedTunnel = tunnels.firstWhere(
            (tunnel) => tunnel.tunnelId == tunnelId,
            orElse: () => state.tunnels.firstWhere(
              (tunnel) => tunnel.tunnelId == tunnelId,
            ),
          );
          
          final updatedTunnels = state.tunnels.map((tunnel) {
            if (tunnel.tunnelId == tunnelId) {
              print('🔧 后台更新隧道详情: ${tunnel.serverName}');
              return updatedTunnel;
            }
            return tunnel;
          }).toList();
          
          state = state.copyWith(tunnels: updatedTunnels);
        },
      );
    }).catchError((error) {
      print('后台刷新单个隧道异常: $error');
    });
  }
}

/// 隧道状态Provider
final tunnelProvider = StateNotifierProvider<TunnelNotifier, TunnelState>(
  (ref) => TunnelNotifier(ref.watch(tunnelRepositoryProvider)),
);

/// 便捷的Provider
final tunnelsProvider = Provider<List<TunnelData>>(
  (ref) => ref.watch(tunnelProvider).tunnels,
);

final tunnelConnectionStatesProvider = Provider<Map<String, TunnelConnectionState>>(
  (ref) => ref.watch(tunnelProvider).connectionStates,
);

/// 特定隧道的连接状态Provider
final tunnelConnectionStateProvider = Provider.family<TunnelConnectionState?, String>(
  (ref, tunnelId) => ref.watch(tunnelProvider).connectionStates[tunnelId],
);
